今天要來補充 schema
的進階用法,延續昨天在 prisma
中使用 DB adapter
的 schema
根據不同的 connect pool
去執行 DB
的內容,但你會發現一件事情,那就是每當你要切換不同的 schema
都要更改 DATABASE_URL
的 .env
。
甚至你的 adapter
也需要去調整
const adapter = new PrismaPg(pool, {
schema: 'test'
})
但如果今天專案一大起來,你有多個 schema
,同時你需要共用不同 schema
的 table
去關聯資料的話,顯然昨日單個 schema
這樣的切換是無法做到的,那今天內容就來教大家如何在 prisma
中使用多個 schema
然後關聯不同 schema
的 table
~
在 prisma
中要使用 multiple database schema
必須要設定 preview feature
在 generator client
這邊,跟昨天的 driverAdapters
一樣
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters", "multiSchema"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
我們除了可以在 DB
自己新增 schema
外,也可以透過 schema.prisma
去幫我們 generate
,只需要在 datasource db
中去指定哪些 schema
需要被使用
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters", "multiSchema"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
schemas = ["base", "transactional"]
}
同時你的 DATABASE_URL
也不需要去加上 schema
的 parameter
,完全不需要更動
//.env
DATABASE_URL="postgresql://root:****@***.***.zeabur.com:***/zeabur"
這時候你會發現當擬定好共用的 schema
後,假設你要新增一個 model
,此時 prisma
會跳一個 error
說他不知道這個 model
屬於哪個 schema
的範疇
所以每當新建一個 model
都會需要用 @@schema
去告訴 prisma
這個 model
屬於哪個 schema
使用,然後除了 model
,enum
也可以指定 schema
~
model User {
id Int @id
orders Order[]
@@schema("base")
}
model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int
@@schema("transactional")
}
enum Size {
Small
Medium
Large
@@schema("transactional")
}
執行完後我們就把 model
migrate
到 DB
>npx prisma migrate dev --name init
然後當你查看現在的 schema
時,你會發現已經成功加進去了~
>zeabur=# \dn;
List of schemas
Name | Owner
---------------+-------------------
base | root
public | pg_database_owner
transactional | root
(3 rows)
那因為預設的 schema
是在 public
所以會沒有 table
是正常的
>zeabur=# \dt;
List of relations
Schema | Name | Type | Owner
--------+--------------------+-------+-------
public | _prisma_migrations | table | root
(1 row)
之後切換 schema
查看 table
,你會發現 prisma
已經成功幫我們區分不同的 table
到各自的 schema
中了~
>zeabur=# SET SEARCH_PATH=base;
SET
>zeabur=# \dt;
List of relations
Schema | Name | Type | Owner
--------+---------+-------+-------
base | User | table | root
(3 rows)
另外有一種情形是,如果你需要不同的 schema
有相同的 table name
也是可行的喔,你只需要改變一下 model name
,然後 @@map
到 table name
以及加上 @@schema
就可以
model BaseConfig {
id Int @id @default(autoincrement())
name String
@@map("config")
@@schema("base")
}
model TransactionalConfig {
id Int @id @default(autoincrement())
name String
@@map("config")
@@schema("transactional")
}
之後我們 migrate
到 DB
>npx prisma migrate dev --name add_profile
你會發現不管是 base Schema
或是 transactional Schema
都有 config
這個 table
了
>zeabur=# SET SEARCH_PATH=base;
SET
>zeabur=# \dt;
List of relations
Schema | Name | Type | Owner
--------+---------+-------+-------
base | User | table | root
base | config | table | root
>zeabur=# SET SEARCH_PATH=transactional;
SET
>zeabur=# \dt;
List of relations
Schema | Name | Type | Owner
---------------+--------+-------+-------
transactional | Order | table | root
transactional | config | table | root
(2 rows)
最後我們在 studio
加上 data
到 BaseConfig
跟 TransactionalConfig
然後執行 index.ts
>tsx watch index.ts
//index.ts
import { Pool } from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from '@prisma/client'
const connectionString = `${process.env.DATABASE_URL}`
const pool = new Pool({ connectionString })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
const main = async () => {
const data = await prisma.baseConfig.findMany({})
const data2 = await prisma.transactionalConfig.findMany({})
console.log(data, data2)
}
你會發現我們成功拿到兩個 schema
中的資料了~
[ { id: 1, name: 'baseConfig' } ] [ { id: 1, name: 'transactionalConfig' } ]
甚至因為 schema.prisma
有 previewFeatures
,所以 adapter
的 schema
就可以直接拿掉了~
// before
const adapter = new PrismaPg(pool, {
schema:'test'
})
// after
const adapter = new PrismaPg(pool)
甚至用了 @@schema
也是可以做關聯資料的~
model User {
id Int @id
orders Order[]
profile Profile?
@@schema("base")
}
model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
@@schema("base")
}
model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int
@@schema("transactional")
}
enum Size {
Small
Medium
Large
@@schema("transactional")
}
query data
也跟以往的方式一樣沒變化~
const orders = await prisma.order.findMany({
where: {
user: {
id: 1,
},
},
})
以上就是所有 schema
的內容,總共花了三天來介紹這個,希望大家可以學到,謝謝大家耐心地閱讀到這邊~
✅ 前端社群 :
https://lihi3.cc/kBe0Y